#include "stream/Topic.h"

#include <vector>
#include <mutex>


#include "stream/impl/rocksdb/Topic.h"

namespace stream {

class Container {
public:
	Container(){
	}
	~Container(){
	}
	int push(std::string && str){
		std::shared_ptr<std::string> tmp(new std::string(std::move(str)));
        if(_data.capacity() != _data.size()){
            _data.push_back(tmp);
            return 0;
        }
        //if need realloc space  then push_back locked
        else{
            std::lock_guard<std::mutex> lock(_mutex);
            _data.push_back(tmp);
            return 0;
        }
	}
	std::shared_ptr<std::string> get(size_t index){
		if(index >= 0 && index < size()){
            if(index < _data.size()){
                return _data[index];	
            }
            //if it's last elem (index == size() -1) then lock and read
            else{
                std::lock_guard<std::mutex> lock(_mutex);
                return _data[index];
            }
		}
		return std::shared_ptr<std::string>();
	}
	void clear(){
        std::lock_guard<std::mutex> lock(_mutex);
		_data.clear();
	}
	size_t size() const{
        std::lock_guard<std::mutex> lock(_mutex);
		return _data.size();
	}
private:
	std::vector<std::shared_ptr<std::string>> _data;
    mutable std::mutex _mutex;
};

class MyTopic : public Topic{
public:
	MyTopic(const std::string & name, const std::string & directory)
	:Topic(name, directory)
	{
	}
	~MyTopic() override{
		this->close();
	}
	int append(const std::string & key, const std::string & value) override{
		std::string s(key + ":" + value);
		return _data.push(std::move(s));
	}
	size_t size() const override{
		return _data.size();
	}
    bool get(const std::string & key, std::string & value) override {
		size_t index = std::stoull(key);
		value = *_data.get(index);
		return true;
	}
	void clear() override {
		_data.clear();
	}

protected:
	bool _open() override{
		return true;
	}
	void _close() override{
	}
private:
	Container _data;
};




Topic* makeTopic(const std::string & name, const std::string & directory){
	//return new MyTopic(name, directory);
	return new ::stream::impl::rocksdb::Topic(name, directory);
}

}//end namespace stream
